{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **线程 vs. 协程**：线程同步原语基于 OS 线程阻塞；协程同步侧重逻辑挂起与调度器配合。混用时要谨慎，避免在协程内直接使用阻塞式 `mutex::lock()` 等操作。\n",
    "- **结构化并发**：C++26 的 sender/receiver 框架旨在为线程与协程提供统一的抽象层，鼓励以组合方式描述并发流程、共享取消状态等。\n",
    "- **编译器支持**：C++23 特性已逐步在主流编译器内实现；C++26 草案特性仍需等待编译器落地，可关注 GCC/Clang/MSVC 的实验性支持。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程同步与并发原语\n",
    "- 互斥量与锁（Mutual Exclusion）\n",
    "- 条件等待与通知（Condition Waiting & Signaling）\n",
    "- 同步计数构件（Barriers, Latches, Semaphores）\n",
    "- 原子与内存模型（Atomics & Memory Ordering）\n",
    "- 一次性初始化与线程局部存储（Initialization & TLS）\n",
    "- 线程管理与结构化并发（Thread Management & Structured Concurrency）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "协程相关同步与协调（Coroutine-Oriented Facilities）\n",
    "- 语言级关键字与底层接口\n",
    "- 标准库 awaitable 与生成器\n",
    "- 协程与 Sender/Receiver 桥接（C++26 草案）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 线程同步与并发原语"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**理解要点**：同步语句关注“线程之间在何时等待/唤醒”，而并发语句关注“如何创建、管理、取消和协调线程和任务执行”。在实际工程中，两类原语常要搭配使用：例如用 `std::jthread` 启动任务，再以 `std::barrier` 控制阶段同步，配合 `std::stop_token` 优雅收尾。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 同步语句\n",
    "\n",
    "| 对比维度         | 闩锁 `std::latch`                        | 栅栏 `std::barrier`                                 | 互斥锁 `std::mutex`        | 条件变量 `std::condition_variable`           | 信号量 `std::counting_semaphore`     | `join()` / `future`                             |\n",
    "| ---------------- | ---------------------------------------- | --------------------------------------------------- | -------------------------- | -------------------------------------------- | ------------------------------------ | ----------------------------------------------- |\n",
    "| 典型同步语句     | `ready.count_down();`<br>`ready.wait();` | `sync.arrive_and_wait();`                           | `std::lock_guard lock(m);` | `cv.wait(lock, cond);`<br>`cv.notify_all();` | `sem.acquire();`<br>`sem.release();` | `worker.join();`<br>`auto v = fut.get();`       |\n",
    "| 设计用途         | 等待 N 个事件完成                        | 多轮次、分阶段同步                                  | 保护共享资源的互斥访问     | 等待条件成立并唤醒                           | 控制资源数量 / 入场许可              | 等待单线程完成或异步结果就绪                    |\n",
    "| 能否重复使用     | ❌ 一次性                                 | ✅ 每轮重置                                          | ✅                          | ✅                                            | ✅                                    | `join()` 一次性；`future` 一次性                |\n",
    "| 是否需要配合锁   | 自身不保护数据                           | 否（仅同步点）                                      | 是（保护临界区）           | 需与互斥锁合用                               | 否（内部计数）                       | 否                                              |\n",
    "| 到达线程是否阻塞 | 仅主动 `wait()` 的线程阻塞               | 每个 `arrive_and_wait()` 的线程都阻塞至所有线程到齐 | 持锁线程独占执行           | 条件满足前等待线程阻塞                       | `acquire` 时计数不足将阻塞           | `join()` 阻塞调用者；`future::get()` 阻塞调用者 |\n",
    "| 典型用途示例     | N 个 worker 完成后主线程继续             | 并行迭代的阶段同步（例如 Jacobi、FFT）              | 保护共享容器、状态机       | 生产者/消费者模式下的条件唤醒                | 控制并发数量、限流、连接池           | 等待单个线程结束或获取异步计算结果              |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 并发语句\n",
    "\n",
    "| 对比维度       | `std::thread`                                     | `std::jthread`（C++20）                                      | `std::async`                              | `std::future` / `std::promise`                    | `std::execution::par` / `par_unseq`        | `std::stop_token` 协作取消                |\n",
    "| -------------- | ------------------------------------------------- | ------------------------------------------------------------ | ----------------------------------------- | ------------------------------------------------- | ------------------------------------------ | ----------------------------------------- |\n",
    "| 典型并发表达式 | `std::thread worker(task);`                       | `std::jthread worker(task);`                                 | `auto fut = std::async(f, args...);`      | `std::promise<int> p; auto fut = p.get_future();` | `std::sort(std::execution::par, ...);`     | `token.stop_requested()`                  |\n",
    "| 生命周期管理   | 需手动 `join()` 或 `detach()`                     | RAII：析构时自动 `join()`（可选取消）                        | 由实现决定同步/异步（`std::launch` 控制） | `promise` 提供结果，`future::get()` 消费          | 算法执行完毕自动收束                       | `std::stop_source` 请求，回调响应         |\n",
    "| 取消/停止支持  | ❌（需自建机制）                                   | ✅ 内建 `stop_token` 传递                                     | 部分支持（需手动检查 `future_status`）    | 需自定义取消协议                                  | ❌（需算法体自定义检查）                    | ✅ 协作式取消，在工作循环中检查 stop 请求  |\n",
    "| 结果返回       | 通过共享数据 / `std::future` / `promise`          | 同 `std::thread`，常配合 `stop_token` 与 `latch`             | `future` 自动返回函数结果                 | `future::get()` 获取 `promise` 设置的值           | 直接在容器上就地修改，或搭配外部收集结构   | —                                         |\n",
    "| 适用场景       | 细粒度线程管理，灵活但易出错                      | 结构化并发、安全退出                                         | 快速提交任务；可同步或异步执行            | 自定义生产者-消费者式结果传递                     | 标准库并行算法（排序、遍历、规约）         | 需要可撤销任务或协作式停止的长期运行线程  |\n",
    "| 额外注意       | 避免忘记 `join`（终止程序）或 `detach` 后资源泄漏 | 需处理 stop 请求（如循环中 `if (token.stop_requested()) break;`) | 默认策略实现依赖：可能同步执行            | `promise` 必须在所有路径上设置值或异常            | 算法主体必须是线程安全的；数据竞争自行避免 | 与 `std::jthread`、回调、条件等待配合使用 |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 互斥量与锁（Mutual Exclusion）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| 工具 / 接口                                           | 头文件           | 标准  | 说明                                               |\n",
    "| ----------------------------------------------------- | ---------------- | ----- | -------------------------------------------------- |\n",
    "| `std::mutex::lock()` / `unlock()`                     | `<mutex>`        | C++11 | 手动加/解锁（必须成对），异常安全需自行保证        |\n",
    "| `std::mutex` / `std::timed_mutex`                     | `<mutex>`        | C++11 | 基础互斥锁（支持阻塞 / 超时）                      |\n",
    "| `std::recursive_mutex` / `std::recursive_timed_mutex` | `<mutex>`        | C++11 | 同线程可重复加锁（慎用避免死锁）                   |\n",
    "| `std::lock_guard`                                     | `<mutex>`        | C++11 | RAII 封装，作用域结束自动解锁                      |\n",
    "| `std::unique_lock`                                    | `<mutex>`        | C++11 | 灵活的 RAII 锁，可延迟锁、手动解锁、与条件变量配合 |\n",
    "| `std::scoped_lock`                                    | `<mutex>`        | C++17 | 同时锁定多个互斥量，避免手动锁顺序导致的死锁       |\n",
    "| `std::shared_mutex`                                   | `<shared_mutex>` | C++17 | 读写锁：多读单写                                   |\n",
    "| `std::shared_lock`                                    | `<shared_mutex>` | C++14 | 共享锁，与 `std::shared_mutex` 配合                |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 条件等待与通知（Condition Waiting & Signaling）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| 工具                                      | 头文件                 | 标准  | 说明                                   |\n",
    "| ----------------------------------------- | ---------------------- | ----- | -------------------------------------- |\n",
    "| `std::condition_variable`                 | `<condition_variable>` | C++11 | 基于 `std::unique_lock` 的 wait/notify |\n",
    "| `std::condition_variable_any`             | `<condition_variable>` | C++11 | 支持任意满足 Lockable 的锁类型         |\n",
    "| `std::atomic::wait()/notify_*` & 自由函数 | `<atomic>`             | C++20 | 以原子变量为条件的阻塞等待与唤醒       |\n",
    "| `std::atomic_flag::wait()/notify_*`       | `<atomic>`             | C++20 | 针对 `atomic_flag` 的等待 / 唤醒       |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 同步计数构件（Barriers, Latches, Semaphores）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| 工具                                                | 头文件        | 标准  | 说明                                |\n",
    "| --------------------------------------------------- | ------------- | ----- | ----------------------------------- |\n",
    "| `std::barrier`                                      | `<barrier>`   | C++20 | 可重复使用的栅栏，可附加 completion |\n",
    "| `std::latch`                                        | `<latch>`     | C++20 | 单次闩，计数减到 0 后释放           |\n",
    "| `std::counting_semaphore` / `std::binary_semaphore` | `<semaphore>` | C++20 | 通用 / 二元信号量，用于控制资源许可 |\n",
    "| `std::barrier` 扩展（`arrive` 等）                  | `<barrier>`   | C++23 | 细化接口，提高灵活度                |\n",
    "| `std::latch::try_wait()`                            | `<latch>`     | C++23 | 非阻塞检测闩是否开放                |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 原子与内存模型（Atomics & Memory Ordering）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| 工具                                       | 头文件     | 标准  | 说明                          |\n",
    "| ------------------------------------------ | ---------- | ----- | ----------------------------- |\n",
    "| `std::atomic<T>` / `std::atomic_flag`      | `<atomic>` | C++11 | 基础原子读写、CAS、各类内存序 |\n",
    "| `std::atomic_ref<T>`                       | `<atomic>` | C++20 | 为现有对象提供原子视图        |\n",
    "| 浮点原子（`std::atomic<float>` 等）        | `<atomic>` | C++23 | 浮点类型的原子操作支持        |\n",
    "| `std::atomic` 的 `wait()` 对更多类型的支持 | `<atomic>` | C++23 | 扩展 `wait()` 的类型约束      |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 一次性初始化与线程局部存储（Initialization & TLS）\n",
    "\n",
    "| 工具                                | 头文件 / 关键字 | 标准  | 说明                             |\n",
    "| ----------------------------------- | --------------- | ----- | -------------------------------- |\n",
    "| `std::once_flag` / `std::call_once` | `<mutex>`       | C++11 | 多线程场景中保证初始化只执行一次 |\n",
    "| `thread_local`                      | 关键字          | C++11 | 每线程独立实例，规避共享同步     |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 线程管理与结构化并发（Thread Management & Structured Concurrency）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| 工具                                                         | 头文件         | 标准          | 说明                                                  |\n",
    "| ------------------------------------------------------------ | -------------- | ------------- | ----------------------------------------------------- |\n",
    "| `std::thread`                                                | `<thread>`     | C++11         | 基础线程封装                                          |\n",
    "| `std::jthread`                                               | `<thread>`     | C++20         | RAII 线程，自动 join，内置停止请求                    |\n",
    "| `std::stop_token` / `std::stop_source` / `std::stop_callback` | `<stop_token>` | C++20         | 协作式线程停止机制                                    |\n",
    "| `std::syncbuf` / `std::osyncstream`                          | `<syncstream>` | C++20         | 线程安全输出缓冲，防止输出交错                        |\n",
    "| **Sender/Receiver 框架（`std::execution`）**<sup>†</sup>     | `<execution>`  | C++26（草案） | 统一的异步抽象，支持结构化并发、调度器、`when_all` 等 |\n",
    "| **`std::run_loop`、`std::execution::start_detached` 等**<sup>†</sup> | `<execution>`  | C++26（草案） | Sender/receiver 的事件循环与便捷工具                  |\n",
    "| **结构化并发算法（`let_value`、`when_all` 等）**<sup>†</sup> | `<execution>`  | C++26（草案） | 组合异步任务、传播错误与取消                          |\n",
    "\n",
    "> <sup>†</sup> C++26 项目基于 WG21 草案（例如 P2300）。最终标准及实现细节可能调整，需关注编译器支持情况。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 协程相关同步与协调（Coroutine-Oriented Facilities）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 语言级关键字与底层接口"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| 工具                                             | 语言 / 头文件 | 标准  | 说明                                |\n",
    "| ------------------------------------------------ | ------------- | ----- | ----------------------------------- |\n",
    "| `co_await`, `co_return`, `co_yield`              | 语言关键字    | C++20 | 协程语法核心                        |\n",
    "| `std::coroutine_handle`, `std::coroutine_traits` | `<coroutine>` | C++20 | 控制协程生命周期，决定 promise 类型 |\n",
    "| `std::suspend_never`, `std::suspend_always`      | `<coroutine>` | C++20 | 简单的 awaiter 适配器               |\n",
    "| `std::noop_coroutine`                            | `<coroutine>` | C++20 | 零开销的空协程 / 占位 handle        |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 标准库 awaitable 与生成器"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| 工具                      | 头文件         | 标准  | 说明                                  |\n",
    "| ------------------------- | -------------- | ----- | ------------------------------------- |\n",
    "| `std::generator`          | `<generator>`  | C++23 | 官方生成器协程，支持范围 for          |\n",
    "| `std::move_only_function` | `<functional>` | C++23 | 用于协程携带不可复制回调              |\n",
    "| `std::expected`           | `<expected>`   | C++23 | 常与协程 promise 合作，表达结果或错误 |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 协程与 Sender/Receiver 桥接（C++26 草案）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| 工具                                                         | 头文件        | 标准          | 说明                                                        |\n",
    "| ------------------------------------------------------------ | ------------- | ------------- | ----------------------------------------------------------- |\n",
    "| **`std::execution` Sender/Receiver 与协程互操作**<sup>†</sup> | `<execution>` | C++26（草案） | 提供 `await_transform` 等桥接，使 `co_await` 发送器成为可能 |\n",
    "| **`std::execution::async_scope`、`when_all`、`let_value` 等**<sup>†</sup> | `<execution>` | C++26（草案） | 构建结构化并发的协程工具，管理协程生命周期与错误传播        |\n",
    "| **`std::generator` 拓展（`next`/`value` 等）**<sup>†</sup>   | `<generator>` | C++26（草案） | 进一步增强生成器接口，优化协程消费体验                      |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 按照“问题场景 × 学习层次 × 工具”分类对照表"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| 题场景（Problem Scenario）               | **层次 1：C++11 基础**<br>（先熟悉的核心工具）               | **层次 2：C++14~C++20 加强**<br>（更好的封装/性能）          | **层次 3：C++20+ 高级同步**<br>（现代线程协调）              | **层次 4：C++23~C++26 协程 & 结构化并发**<br>（异步/协程融合） |\n",
    "| ---------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |\n",
    "| **保护共享数据**<br>避免数据竞争         | `std::mutex` + `lock()/unlock()`<br>`std::lock_guard` / `std::unique_lock` | `std::scoped_lock`（批量锁）<br>`std::shared_mutex` + `std::shared_lock`（多读单写） | `std::atomic<T>`（含 `atomic_ref`）<br>`std::atomic` 浮点支持 | 在协程中封装 awaitable 的锁适配器<br>（如 sender/receiver awaitable） |\n",
    "| **等待状态变化**<br>条件满足再继续       | `std::condition_variable` + `std::unique_lock`<br>`std::future` / `std::promise` | ——（基础方案已足够）                                         | `std::atomic::wait()/notify_*`<br>`std::counting_semaphore` / `std::binary_semaphore` | 协程中 `co_await` 自定义 awaitable<br>或 `std::execution` sender/receiver |\n",
    "| **批量同步**<br>多线程同时到达/释放      | 手写计数器 + `condition_variable` 或 `future`                | ——                                                           | `std::barrier`（可重用带 completion）<br>`std::latch`（一次性栅栏） | `std::execution::when_all` 等发送器组合（C++26 草案）<br>协程中 await 这些发送器 |\n",
    "| **一次性初始化 / TLS**                   | `std::once_flag` + `std::call_once`<br>`thread_local`        | ——                                                           | ——                                                           | 利用 sender/receiver + `async_scope` 确保初始化流程统一（草案） |\n",
    "| **任务结果 / 请求-响应**                 | `std::async` / `std::future` / `std::promise`<br>`std::packaged_task` | ——                                                           | 将 `std::future` 与协程/线程结合（桥接）                     | `std::generator`（生产序列）<br>`std::expected` 处理返回/错误<br>发送器 `let_value` / `then` 等组合 |\n",
    "| **线程生命周期管理**<br>启动、停止、清理 | `std::thread` + 手工 `join()`                                | ——                                                           | `std::jthread`（析构自动 join）<br>`std::stop_token` / `std::stop_source` / `std::stop_callback` | `std::execution::run_loop`、`start_detached`（草案）<br>结构化并发统筹多个任务 |\n",
    "| **线程安全日志 / 输出**                  | 手动加锁打印                                                 | ——                                                           | `std::syncbuf` / `std::osyncstream`（避免输出交错）          | 在协程执行器里统一调度输出任务，或使用 sender/receiver 流控  |\n",
    "| **协程生产消费 / 数据管线**              | ——（可用线程同步原语包装）                                   | ——                                                           | `std::counting_semaphore` + 自定义 awaiter（协程友好同步）   | `std::generator` + `co_yield` 管线<br>`std::execution` sender/receiver await 化（C++26 草案） |\n",
    "| **结构化并发 / 组合异步任务**            | 手动跟踪 `future` / `thread`                                 | ——                                                           | `std::barrier` + 手写调度                                    | `std::execution::async_scope`、`when_all`、`let_value` 等（C++26 草案）构建结构化并发 |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# C++17 支持线程同步与并发原语代码示例"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```shell\n",
    "sudo apt update\n",
    "sudo apt install libgtest-dev\n",
    "sudo apt install libgmock-dev \n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| 类                                                           | 示例                                                         | 说明                                                         |\n",
    "| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |\n",
    "| 互斥量与锁（Mutual Exclusion）                               | 01_mutex<br>03_timed_mutex<br>04_shared_mutex<br>05_recursive_mutex<br>06_scoped_lock | 覆盖基础互斥量、定时互斥量、共享互斥量、递归互斥量，以及多锁场景下的死锁规避。 |\n",
    "| 条件等待与通知（Condition Waiting & Signaling）              | 02_condition_variable<br>12_condition_variable_any           | 展示标准条件变量与通用条件变量的等待/通知机制，以及与读写锁协同的场景。 |\n",
    "| 同步计数构件（Barriers, Latches, Semaphores）                | 暂无                                                         | 当前示例未涵盖，可增补 `std::latch`、`std::barrier`、`std::counting_semaphore` 等测试。 |\n",
    "| 原子与内存模型（Atomics & Memory Ordering）                  | 07_atomic                                                    | 验证原子操作在多线程计数中的正确性，强调内存同步保障。       |\n",
    "| 一次性初始化与线程局部存储（Initialization & TLS）           | 08_once_flag                                                 | 使用 `std::once_flag` 与 `std::call_once` 确保初始化逻辑仅执行一次。 |\n",
    "| 线程管理与结构化并发（Thread Management & Structured Concurrency） | 09_async<br>10_promise<br>11_packaged_task                   | 涵盖 `std::async`、`std::promise`/`std::future` 与 `std::packaged_task` 等任务管理与结果传递方式。 |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## `std::thread`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "业务场景示例\n",
    "\n",
    "1. **并行任务分解**\n",
    "    将耗时计算或数据处理划分为多个子任务，由多个线程并行执行，缩短总体执行时间。例如图像处理的多块并行滤波、数值运算的分片计算。\n",
    "2. **异步后台作业**\n",
    "    主线程负责响应用户界面或网络请求，`std::thread` 启动后台线程执行日志写入、数据同步、文件下载等耗时操作，避免阻塞前台流程。\n",
    "3. **实时监控 / 轮询服务**\n",
    "    为传感器数据采集、网络心跳检测、定时任务调度等场景分别启动线程，长期运行并监视特定事件或资源状态。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用注意事项\n",
    "\n",
    "- **明确线程生命周期**：创建线程后必须确保在对象销毁前 `join()` 或 `detach()`，否则程序会调用 `std::terminate()`。\n",
    "- **传递参数与所有权**：通过 `std::thread` 传参时，会对参数按值拷贝；需要引用时使用 `std::ref` / `std::cref`。注意资源所有权转移与对象有效期。\n",
    "- **同步共享数据**：多个线程访问共享状态时需要互斥或其他同步手段（`std::mutex`、`std::atomic`、条件变量等）以避免数据竞争。\n",
    "- **异常安全**：线程函数抛出的异常默认会调用 `std::terminate()`，需要在线程内部捕获并妥善处理或传递错误信息。\n",
    "- **线程数量规划**：线程过多会导致频繁上下文切换，反而降低性能。依据硬件核心数、任务特性和调度策略合理创建线程数。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "潜在缺陷 / 局限\n",
    "\n",
    "| 问题                     | 说明                                                         |\n",
    "| ------------------------ | ------------------------------------------------------------ |\n",
    "| 手动管理复杂             | 线程创建、同步、销毁都要手动编排，容易出现资源泄漏、死锁、竞态条件等难以排查的问题。 |\n",
    "| 可移植性限制             | 不同平台对线程栈大小、调度策略、可用线程数有差异，一套策略未必在所有系统表现一致。 |\n",
    "| 性能不可预测             | 线程切换开销、缓存伪共享、锁争用等会让性能难以线性扩展，可能出现“越加线程越慢”。 |\n",
    "| 调试难度大               | 并发缺陷通常表现为偶发 bug，复现和调试成本高，需要借助专门工具或复杂日志。 |\n",
    "| 与线程池相比灵活但成本高 | 频繁创建/销毁线程代价大，适合数量有限、生命周期明确的任务；批量短任务更推荐线程池或 `std::async`。 |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 自动管理线程创建、同步、销毁的工具建议"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| 工具 / 库                                                    | 特点                                                         | 适用场景                                             |\n",
    "| ------------------------------------------------------------ | ------------------------------------------------------------ | ---------------------------------------------------- |\n",
    "| **`std::jthread` (C++20+)**                                  | 构造时自动启动；析构前若未调用 `detach()` 会自动 `join()`；支持 `stop_token` 协作式停止。 | 简化生命周期管理，适合需要可取消的后台任务。         |\n",
    "| **`std::async`**                                             | 通过任务获得 `std::future`，构造后即执行（延迟或立即由实现决定）；析构时自动同步。 | 一次性异步任务，需获取结果或异常的场景。             |\n",
    "| **线程池库 (如 <br/>[`BS::thread_pool`](https://github.com/bshoshany/thread-pool) <br/>, `ctpl` <br/>, `Boost::asio::thread_pool` <br/>, `concurrencpp` <br/>, `folly::CPUThreadPoolExecutor`) <br/>** | 预先创建一组工作线程，自动调度提交的任务；避免频繁创建销毁线程。 | 大量短任务、任务数量动态变化、响应速度要求高的服务。 |\n",
    "| **`Intel oneTBB` / `Threading Building Blocks`**             | 高层并行算法、任务调度器、流水线接口等；自动负载均衡。       | 数据并行、流水线处理、复杂图形工作负载。             |\n",
    "| **`OpenMP`**                                                 | 基于编译器指令（pragma）自动并行化循环和任务。               | 数值计算、科学计算等对性能敏感的批量操作。           |\n",
    "| **`Qt Concurrent`, `QThreadPool`**                           | 在 Qt 生态内提供任务调度与线程池，易与 GUI 事件循环集成。    | 桌面应用、多媒体等需要 GUI + 后台任务的场合。        |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 等待方式"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| 方法                                    | 特点                                 | 适用场景                          |\n",
    "| --------------------------------------- | ------------------------------------ | --------------------------------- |\n",
    "| `std::this_thread::yield()`             | 立即出让时间片，不阻塞；无保证。     | 短暂忙等，自旋时避免 100% CPU。   |\n",
    "| `std::this_thread::sleep_for(duration)` | 线程阻塞指定时长，至少等待该时长。   | 可以容忍延迟，希望降低 CPU 占用。 |\n",
    "| 条件变量、`std::future` 等              | 线程阻塞直到事件发生，带有唤醒机制。 | 需要明确同步、避免自旋的场景。    |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "常见使用场景\n",
    "\n",
    "- **自旋锁 / 无锁同步**：在 CAS 循环或等待条件满足时，使用 `yield()` 减少 CPU 忙等。\n",
    "- **测试或演示代码**：帮助触发更多线程切换，使竞态问题更容易暴露。\n",
    "- **轻量级等待**：等待某个条件有望很快满足，但不想使用休眠（`sleep_for`）造成延迟。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "std::atomic<bool> ready{false};\n",
    "\n",
    "void worker_without_yield() {\n",
    "    // 不调用 yield，自旋会持续占用 CPU\n",
    "    while (!ready.load(std::memory_order_acquire)) {\n",
    "        // 忙等\n",
    "    }\n",
    "    std::cout << \"[no yield] detected ready\\n\";\n",
    "}\n",
    "\n",
    "void worker_with_yield() {\n",
    "    while (!ready.load(std::memory_order_acquire)) {\n",
    "        // 让出时间片，其他线程更易获得执行机会\n",
    "        std::this_thread::yield();\n",
    "    }\n",
    "    std::cout << \"[yield] detected ready\\n\";\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [01_mutex](./threadcodes/01_mutex/mutex_test.cpp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- https://en.cppreference.com/w/cpp/thread/mutex.html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 通过 `std::mutex` 配合 RAII 封装（`std::lock_guard`、`std::unique_lock`）来保护共享资源的临界区，确保同一时间只有一个线程能够修改共享数据。\n",
    "- 进入临界区时构造 `std::lock_guard<std::mutex>` 或 `std::unique_lock<std::mutex>` 对象，构造函数自动调用 `mutex.lock()`，作用域结束时析构函数自动 `unlock()`，避免异常路径漏解锁。\n",
    "- **即时尝试/快速失败**：当需要避免阻塞时，可使用 `mutex.try_lock()` 或 `std::unique_lock` 的 `std::try_to_lock` 策略实现非阻塞尝试，适合对响应性要求高或需要自定义退避策略的场景。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "业务场景示例\n",
    "\n",
    "- **共享计数器或统计逻辑**\n",
    "   多个线程汇总日志、事件或订单数量时，需对全局计数器进行互斥保护，确保计数结果准确。\n",
    "- **库存/余额更新**\n",
    "   电商库存、账户余额等共享资源在多线程校对和修改时，通过互斥锁串行化访问以防竞态条件。\n",
    "- **配置/缓存初始化**\n",
    "   第一次加载配置文件或构建缓存时，锁住初始化过程，防止多个线程重复构建或读写未初始化的数据结构。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用注意事项\n",
    "\n",
    "- **缩小锁粒度**：仅在必要的临界区持锁，减少阻塞，提高并发度。\n",
    "- **配合 RAII**：优先使用 `std::lock_guard`、`std::unique_lock` 等 RAII 封装，防止忘记解锁导致死锁。\n",
    "- **异常安全**：确保异常路径中也能释放资源；RAII 对象是最简单的保障。\n",
    "- **避免长时间持锁 I/O**：长时间持锁会阻塞其他线程，可将 I/O 或计算操作移出临界区。\n",
    "- **识别锁竞争热点**：在高并发场景监控锁等待时间，必要时对资源或读写策略做细粒度调整。\n",
    "- **合理使用 `try_lock()`**：\n",
    "  - 非阻塞尝试获取锁，获取成功返回 `true`，失败立即返回 `false`，可用于避免线程长时间阻塞。\n",
    "  - 适合尝试性任务、后台刷新、抢占式工作流等；获取失败时可执行其他任务或采取退避策略（`yield`、随机等待）。\n",
    "  - 避免无退避的忙等：频繁 `try_lock()` + 自旋容易造成活锁或 CPU 浪费，可结合退避或限制重试次数。\n",
    "  - 搭配 RAII：`std::unique_lock<std::mutex> lock{m, std::try_to_lock}; if (lock.owns_lock()) { ... }`，确保成功后仍由 RAII 负责解锁。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "潜在缺陷 / 局限\n",
    "\n",
    "- **性能瓶颈**：单一互斥锁会串行化所有访问，成为热点，限制吞吐。\n",
    "- **死锁风险**：多锁嵌套缺乏顺序，调用链复杂时容易造成死锁。\n",
    "- **公平性**：存在操作优先级倒置的风险，优先级低线程阻塞时间长，除非操作系统提供优先级继承。\n",
    "- **可扩展性不足**：在读写多的场景，互斥锁阻止读写并发，需要更先进的原语（如 `std::shared_mutex`）。\n",
    "- **上下文切换开销**：频繁的锁争用会触发核间唤醒/睡眠，增加调度成本；可视情况使用 `try_lock()` + 退避或读写锁降低争用。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [02_condition_variable](./threadcodes/02_condition_variable/condition_variable_test.cpp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- https://en.cppreference.com/w/cpp/thread/condition_variable.html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**核心对象**：`std::condition_variable` + `std::unique_lock<std::mutex>`。\n",
    "\n",
    "**作用**：让线程在条件未满足时阻塞，等待其他线程修改共享状态并唤醒；典型应用于线程间同步和协作。\n",
    "\n",
    "**基本流程**：\n",
    "\n",
    "1. 等待方先获取互斥锁（`std::unique_lock`），然后调用 `wait()`。\n",
    "2. `wait()` 自动释放互斥锁并挂起线程，直到被 `notify_one()` / `notify_all()` 唤醒。\n",
    "3. 被唤醒后，`wait()` 重新持有互斥锁，并重新检查条件（防止虚假唤醒）。\n",
    "4. 条件满足 => 退出等待，继续执行临界区之后的逻辑。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "业务场景示例\n",
    "\n",
    "- **生产者-消费者队列**\n",
    "   多个生产者线程将任务放入队列，消费者线程在队列为空时等待，通过条件变量在数据到来时被唤醒。\n",
    "- **线程池任务调度**\n",
    "   工作线程在空闲时阻塞等待，有新任务提交时由管理线程触发唤醒，避免忙等。\n",
    "- **阶段性工作流协调**\n",
    "   某些线程必须等待其他线程完成特定阶段（例如配置加载、资源准备），完成后通过条件变量通知等待者继续执行。\n",
    "- **限流 / 资源池**\n",
    "   当资源池枯竭，借助条件变量阻塞申请线程，直到资源归还后再唤醒继续。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用注意事项\n",
    "\n",
    "- **始终搭配互斥锁**：调用 `wait` 前必须持有与条件变量配套的互斥锁，以保证检测条件和进入等待之间的原子性。\n",
    "- **循环检查条件**：`wait` 返回后需在循环中重新检查条件（防止虚假唤醒、同时唤醒多个线程后条件不再满足）。\n",
    "- **明确通知范围**：根据场景选择 `notify_one` 或 `notify_all`，避免唤醒过多线程造成惊群，也避免遗漏。\n",
    "- **避免遗漏通知**：修改共享状态后再发通知，顺序相反可能导致等待线程错过信号。\n",
    "- **使用 `unique_lock`**：`std::condition_variable` 要求 `std::unique_lock`，提供灵活的锁释放与重新获取能力。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "潜在缺陷 / 局限\n",
    "\n",
    "- **虚假唤醒（Spurious Wakeup）**：即使条件未满足也可能返回，误用会造成逻辑错误。\n",
    "- **惊群效应**：进行 `notify_all` 时唤醒大量线程争抢资源，会降低效率。\n",
    "- **易发生竞态**：若后端共享状态与通知顺序不当，会出现“通知丢失”或死锁。\n",
    "- **调试困难**：涉及多个线程、复杂状态机，排查阻塞或遗漏通知的问题较为困难。\n",
    "- **性能开销**：频繁等待/唤醒会导致系统调用与上下文切换开销，需关注通知频率与粒度。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### wait_for 状态装换"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "状态含义\n",
    "\n",
    "- **Active / Running（活动中）**<br>\n",
    "   线程持有互斥量，执行临界区代码，尚未调用 `wait_for`。\n",
    "- **Ready-To-Wait（准备进入等待）**<br>\n",
    "   线程持有互斥量并调用 `wait_for`。此时函数会：\n",
    "  1. 将调用线程加入条件变量的等待队列；\n",
    "  2. 原子地释放关联的互斥量；\n",
    "  3. 挂起线程，进入 `Waiting` 状态。\n",
    "- **Waiting（阻塞等待）**<br>\n",
    "   线程在条件变量的等待队列中，等待以下事件之一：\n",
    "  1. 被 `notify_one()` 唤醒；\n",
    "  2. 发生超时；\n",
    "  3. 收到意外的“伪唤醒”（spurious wakeup）。\n",
    "- **Wakeup-Reacquire（被唤醒，尝试重新获取互斥量）**<br>\n",
    "   事件触发后，线程从等待队列移除，竞争互斥量。一旦重新获得互斥量，就返回到 `Active` 状态（由用户代码检查谓词决定是否离开等待循环）。\n",
    "- **Timeout（等待超时）**<br>\n",
    "   如果在给定时间内没有收到满足条件的通知，`wait_for` 返回 `std::cv_status::timeout`，线程重新拥有互斥量并回到 `Active`，通常用户会根据返回值决定是否再次等待。\n",
    "- **Spurious Wakeup（伪唤醒）**<br>\n",
    "   条件变量允许无原因的唤醒。线程重新获得互斥量后应再次检查谓词，如果条件未达成，则继续调用 `wait_for` 返回 `Waiting`。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```mermaid\n",
    "stateDiagram-v2\n",
    "    [*] --> Active : 线程运行 \\n 持有互斥量\n",
    "    Active --> ReadyToWait : 调用 wait_for(lock, pred, duration)\n",
    "    ReadyToWait --> Waiting : 自动释放互斥量 \\n 加入等待队列\n",
    "    Waiting --> WakeupReacquire : notify_one() 或伪唤醒\n",
    "    Waiting --> Timeout : 超时时钟到期\n",
    "    WakeupReacquire --> Active : 重新获得互斥量\n",
    "    Timeout --> Active : wait_for 返回 timeout\n",
    "    Active --> Waiting : 谓词未满足 \\n 再次调用 wait_for\n",
    "    Active --> [*] : 谓词满足，退出等待循环\n",
    "```\n",
    "\n",
    "![status](./images/status.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### `wait_for / wait_until`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在条件变量场景中，除基本的 `wait()` 外，还常用两种带超时的等待方式：\n",
    "\n",
    "- `cv.wait_for(lock, duration, predicate)`：在给定的持续时间内等待条件变为真，超时返回 `false`。\n",
    "- `cv.wait_until(lock, time_point, predicate)`：等待直到指定的时间点，若到时条件仍未满足则返回 `false`。\n",
    "\n",
    "这样可以避免线程无限期阻塞，便于实现超时重试、失败降级等业务策略。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "业务应用示例\n",
    "\n",
    "1. **重试/轮询**：使用 `wait_for` 定期检查后台任务状态，若超时可记录日志或执行备用方案。\n",
    "2. **截止时间控制**：`wait_until` 可实现“在某个绝对时间点前等待结果，否则终止并降级”的需求，例如限时秒杀的库存锁定。\n",
    "3. **资源租约 / 心跳**：线程在一定时间内没有收到更新即判定超时，对资源进行回收或重建。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "配套注意事项\n",
    "\n",
    "- 使用带谓词的 `wait_for` / `wait_until`，自动在内部循环检查条件，防止虚假唤醒。\n",
    "- 超时返回 `false` 时，记得根据业务逻辑执行补救措施，例如重试、回滚、告警。\n",
    "- 使用绝对时间 (`wait_until`) 时建议搭配 `steady_clock`，避免系统时间调整带来的误差。\n",
    "- 仍需保证所有访问共享状态的代码段都持有同一把互斥锁。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### `std::condition_variable` 为什么搭配 `std::unique_lockstd::mutex`?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. **`wait()` 需要在内部“解锁 + 挂起 + 重新加锁”的原子操作**\n",
    "\n",
    "- 当线程调用 `cv.wait(lock)` 时，需要 **先释放互斥锁**，再把线程挂起。\n",
    "- 唤醒后 `wait()` 还要 **重新获得互斥锁**，以便继续访问共享状态。\n",
    "- 这一套操作必须是原子的，不能在释放锁和挂起之间让其他线程插入修改条件，否则会丢失通知或造成竞态。\n",
    "\n",
    "`std::unique_lock` 提供了 `unlock()`/`lock()` 成员函数，`condition_variable` 可以调用它们来保证上述过程安全完成。而 `std::lock_guard` 没有这类接口，只能自动加锁/解锁，无法满足 `wait()` 的需求。\n",
    "\n",
    "\n",
    "\n",
    "2. **灵活控制锁的持有与释放**\n",
    "\n",
    "- `unique_lock` 支持延迟加锁、提前解锁、手动重新加锁等操作，方便我们在唤醒后根据逻辑选择何时释放锁。\n",
    "- 这些能力在使用条件变量时很常用，例如在处理完条件后尽早 `unlock()`，缩小临界区。\n",
    "\n",
    "\n",
    "\n",
    "3. **符合条件变量接口要求**\n",
    "\n",
    "- `std::condition_variable::wait` 的签名明确要求参数类型满足 `std::unique_lock<std::mutex>` 的接口约束；这是标准库层面对正确性和可移植性的保证。\n",
    "\n",
    "\n",
    "\n",
    "小结\n",
    "\n",
    "- `std::condition_variable` 需要通过 `unique_lock` 来安全地“释放锁并等待→被唤醒后重新加锁”。\n",
    "- `unique_lock` 提供的灵活锁管理能力（可显式 `lock/unlock`）正是实现这一流程所必需的。\n",
    "- 因此在条件变量场景中，应优先使用 `std::unique_lock<std::mutex>`，而不是功能受限的 `std::lock_guard`。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [03_timed_mutex](./threadcodes/03_timed_mutex/timed_mutex_test.cpp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**`std::timed_mutex`** 是带有超时功能的互斥锁，除了 `lock()` / `unlock()` / `try_lock()` 外，还提供\n",
    "\n",
    "- `bool try_lock_for(Duration timeout);`\n",
    "- `bool try_lock_until(TimePoint deadline);`\n",
    "   以限制锁的等待时间。\n",
    "\n",
    "**适用场景**：当线程需要访问共享资源，却不能无限期阻塞时（UI 线程、RPC 超时、后台巡检等），可以通过超时机制在等待失败后执行降级或重试。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "业务场景示例\n",
    "\n",
    "- **有限等待的资源访问**\n",
    "   当线程需要访问某资源但不能无限期阻塞（如 UI 线程或实时任务），通过 `try_lock_for` 或 `try_lock_until` 设置等待上限，避免界面卡死或超出时限。\n",
    "- **故障切换/降级策略**\n",
    "   在服务调用链中，仅在指定超时时间内等待上游资源锁；若超时，则触发降级逻辑或转入备用路径。\n",
    "- **分布式/远程资源模拟**\n",
    "   当使用互斥锁保护对网络、文件或数据库的访问，需要在超时后记录告警或尝试其他节点，避免线程长时间阻塞。\n",
    "- **后台维护任务**\n",
    "   定期任务尝试获取锁执行维护，如果无法在限定时间内获取，跳过本轮，以减少对主业务的影响。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用注意事项\n",
    "\n",
    "- **合理选择超时时间**：时间过短会导致频繁超时，过长又失去“有限等待”的意义，应根据业务 SLA 调整。\n",
    "- **判断返回值**：`try_lock_for`/`try_lock_until` 返回 `false` 表示超时获取失败，必须处理失败分支（日志、重试、降级等）。\n",
    "- **保持互斥锁的基本约束**：加锁后需确保及时释放，推荐配合 `std::unique_lock` 管理生命周期。\n",
    "- **与条件变量搭配**：若需要在锁等待超时后执行额外逻辑，可结合条件变量与 timed mutex，共同控制等待时间与资源状态。\n",
    "- **避免忙碌重试**：连续快速重试获取锁会造成 CPU 浪费，可在失败后适当等待或采用指数退避。\n",
    "- **跨平台行为差异**：不同平台对计时精度、时钟来源支持程度不同，需验证在目标环境下的准确性。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "潜在缺陷 / 局限\n",
    "\n",
    "- **超时并不释放资源**：超时仅表示未拿到锁，并不能打断持锁线程；若持锁线程长时间不释放，问题仍然存在。\n",
    "- **复杂性提升**：引入超时分支后，代码需要处理更多状态（成功、超时、异常），增加维护难度。\n",
    "- **时钟漂移影响**：系统时钟调整可能影响 `try_lock_until`，需确保使用稳健的时间源（如 `steady_clock`）。\n",
    "- **性能开销**：与普通互斥相比，timed mutex 在实现层面可能更重，频繁使用会产生额外的系统调用和调度成本。\n",
    "- **失效重入风险**：超时失败后，未妥善处理共享状态或清理逻辑，可能造成数据不一致或资源泄漏。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [04_shared_mutex](./threadcodes/04_shared_mutex/shared_mutex_test.cpp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**`std::shared_mutex`**：自 C++17 引入的读写锁，允许多个读者线程并发持有“共享锁”（共享访问权），而写者线程需要获取“独占锁”（独占访问权）。\n",
    "\n",
    "**锁的类型**：\n",
    "\n",
    "- 读操作：`std::shared_lock<std::shared_mutex>`（共享锁，可并发持有）。\n",
    "- 写操作：`std::unique_lock<std::shared_mutex>` / `std::scoped_lock<std::shared_mutex>`（独占锁，阻塞所有读者）。\n",
    "\n",
    "**效果**：读多写少场景下显著提升吞吐量，因为读者无需彼此等待；写入时仍能保障数据一致性。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "业务场景示例\n",
    "\n",
    "- **读多写少的配置中心**\n",
    "   多个线程频繁读取配置信息，偶尔有更新操作。使用 `shared_mutex` 允许多个读者同时获取共享锁，提高读取吞吐量。\n",
    "- **缓存查询与刷新**\n",
    "   热点缓存（如商品详情、用户画像）读取频繁，刷新或失效更新较少，读线程使用共享锁，写线程使用独占锁更新数据。\n",
    "- **不可变数据快照**\n",
    "   分析线程需要在不阻塞其他读者的情况下获取一致快照，写线程更新时短暂获取独占锁，避免数据撕裂。\n",
    "- **统计报表生成**\n",
    "   统计线程周期性读大量业务指标，写线程以较低频率更新指标，使读线程在共享锁下并行执行。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用注意事项\n",
    "\n",
    "- **区分读写锁类型**：读取操作使用 `std::shared_lock`，写入操作使用 `std::unique_lock` 或 `std::scoped_lock`，确保锁类型与操作一致。\n",
    "- **防止写锁饥饿**：高频读请求可能导致写锁长时间等待，可根据需求采用 `std::shared_mutex` 或 `std::shared_timed_mutex` 并结合策略限制读锁持有时间。\n",
    "- **避免在持有共享锁时升级**：标准库不支持直接从共享锁升级到独占锁，升级会导致死锁风险，应先释放共享锁再获取独占锁，或通过更复杂的升级机制实现。\n",
    "- **控制临界区长度**：即使是共享锁，持锁时间过长依然会阻塞写者；写锁的临界区更需简短，以降低对读者的影响。\n",
    "- **与条件变量配合注意类型**：如需配合条件变量等待，需使用 `std::condition_variable_any`，因为标准 `condition_variable` 仅支持 `unique_lock`。\n",
    "- **考量平台支持**：`shared_mutex` 在 C++17 标准中引入，确保编译器和标准库实现支持并具备良好性能。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "潜在缺陷 / 局限\n",
    "\n",
    "- **写锁饥饿**：大量读者持续持有共享锁时，写线程可能一直得不到独占锁，导致更新延迟甚至饥饿。\n",
    "- **实现复杂度**：相较普通互斥锁，读写锁的实现和调试更复杂；不合理使用可能引入难以察觉的竞态。\n",
    "- **读性能影响写吞吐**：在写操作频繁的场景，读写锁会频繁从共享模式切换至独占模式，导致性能反而低于普通互斥锁。\n",
    "- **锁管理开销**：共享锁内部维护读者计数等结构，获取/释放的开销通常大于简单互斥锁，对高频短临界区可能不划算。\n",
    "- **一致性要求高**：若读操作需要观察多个共享状态，必须保证在单个共享锁下访问，否则读者可能看到不一致的数据。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [05_recursive_mutex](./threadcodes/05_recursive_mutex/recursive_mutex_test.cpp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **`std::recursive_mutex`** 是一种可重入互斥量：同一线程在已经持有锁的情况下，可以再次成功加锁，而不会产生自陷的死锁。\n",
    "- 每次 `lock()` 都必须对应一次 `unlock()`；重入的层数越多，调用者就需要按相同次数释放。\n",
    "- 常与 RAII 包装（`std::lock_guard<std::recursive_mutex>`、`std::unique_lock<std::recursive_mutex>`）一起使用，保证异常安全。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "业务场景示例\n",
    "\n",
    "- **递归函数访问共享资源**\n",
    "   递归算法在每一层都需访问同一临界资源，使用递归互斥量避免在深层递归中重复请求锁而死锁。\n",
    "- **复杂类内部调用链**\n",
    "   类成员函数之间相互调用，且多个函数都需要对同一对象状态加锁。若外层函数已持锁，递归互斥量允许内层函数再次加锁而不自死锁。\n",
    "- **可重入回调**\n",
    "   事件回调中有可能再次触发同一回调路径，例如 GUI 事件或脚本引擎调用，需要在持锁的同时允许重入执行。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用注意事项\n",
    "\n",
    "- **仅在必要时选用**：优先设计避免重入的锁策略，确认无法重构后再考虑 `recursive_mutex`。\n",
    "- **谨慎控制锁层数**：虽然允许同一线程多次加锁，但应尽量简化调用层级，避免过深的重入导致逻辑复杂度提升。\n",
    "- **配合 RAII**：仍建议使用 `std::lock_guard<std::recursive_mutex>` 或 `std::unique_lock<std::recursive_mutex>` 确保异常安全。\n",
    "- **保持锁粒度合理**：递归互斥量并不代表可以长时间持锁，应保持临界区短小，以减少对其他线程的阻塞。\n",
    "- **警惕嵌套调用状态**：在多层重入中容易忽视共享状态变更顺序，需明确每层调用的前置条件与后置状态。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "潜在缺陷 / 局限\n",
    "\n",
    "- **易掩盖设计问题**：递归互斥量使得代码可以“不经设计”地重入，可能隐藏更深层的架构问题或逻辑循环。\n",
    "- **性能与资源开销更高**：相比普通互斥量，需要维护重入计数等额外数据结构，获取和释放的开销更大。\n",
    "- **死锁仍可发生**：跨线程使用时仍存在死锁风险；当多个递归互斥量交叉使用时问题更复杂。\n",
    "- **逻辑复杂度提升**：重入层数增加后，锁的持有状态难以推理，调试和验证正确性更加困难。\n",
    "- **不能解决跨线程重入**：递归互斥量只允许同一线程重复加锁，无法解决不同线程间的互斥需求。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [06_scoped_lock](./threadcodes/06_scoped_lock/scoped_lock_test.cpp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- `std::scoped_lock` 在构造时一次性获取传入的所有互斥量，采用 `std::lock` 实现死锁避免策略。\n",
    "- 支持任意数量的 `Lockable` 对象（满足 `lock()` / `unlock()` 接口即可）。\n",
    "- 析构时自动释放全部锁，保证异常情况下也能正确解锁。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "业务场景示例\n",
    "\n",
    "- **多互斥量联合加锁**\n",
    "   在操作多个共享资源（例如订单表与库存表）时，需要一次性获取多把互斥锁。`std::scoped_lock` 支持同时管理多个锁并防止死锁。\n",
    "- **统一 RAII 管理**\n",
    "   对象成员函数中需要在进入时自动加锁、退出时自动解锁；`scoped_lock` 通过 RAII 机制简化锁生命周期管理，避免异常路径遗忘解锁。\n",
    "- **组合锁保护复合结构**\n",
    "   当数据结构由多个互斥量保护不同部分（如主索引与缓存映射），可使用 `scoped_lock` 同时持有这些锁以完成跨结构操作。\n",
    "- **替代传统 `std::lock` + `std::lock_guard` 模式**\n",
    "   传统做法先用 `std::lock` 获取多把锁，再用 `std::adopt_lock` 构造 `lock_guard`。`scoped_lock` 将流程整合为一条语句，避免错误。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用注意事项\n",
    "\n",
    "- **正确传入锁对象顺序**：`scoped_lock` 内部使用 `std::lock` 进行死锁避免，传入锁的顺序在调用点保持一致即可，避免动态决定顺序。\n",
    "- **适当控制锁粒度**：尽管可以同时持有多把锁，但应确保临界区尽可能短，减少对其他线程的阻塞。\n",
    "- **异常安全**：`scoped_lock` 在析构时自动释放锁，能很好地处理异常场景；仍需注意在构造成功前抛出的异常可能导致部分锁未获锁成功，需设计好回退逻辑。\n",
    "- **确保锁类型兼容**：`scoped_lock` 支持互斥量、共享互斥量等多种锁类型，但必须满足 `Lockable` 要求（提供 `lock`/`unlock` 接口）。\n",
    "- **谨慎搭配条件变量**：若需要等待条件变量，应使用 `std::unique_lock`，因为条件变量需要支持手动 unlock/relock；`scoped_lock` 在当前标准下不支持解锁再锁定。\n",
    "- **考虑性能成本**：一次性锁多个互斥量会增加争用窗口，必要时评估是否可以拆分操作或引入读写锁等策略。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "潜在缺陷 / 局限\n",
    "\n",
    "- **无法手动解锁再锁定**：与 `unique_lock` 不同，`scoped_lock` 不支持在作用域中手动释放锁，限制了需要 finer control（如条件变量等待）的场景。\n",
    "- **持有多锁的复杂度**：同时持有多把锁的场景更容易造成逻辑复杂和调试困难，错误时影响范围扩大。\n",
    "- **阻塞时间可能更长**：多锁联动导致锁获取需要等待所有锁可用，可能比单锁场景拥有更高的阻塞概率。\n",
    "- **不支持转移所有权**：`scoped_lock` 不可移动，无论复制或移动都会被禁用，无法在函数之间转移锁的持有权。\n",
    "- **兼容性需求**：需要 C++17 及以上标准支持，旧代码或旧编译器环境可能无法使用。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [07_atomic](./threadcodes/07_atomic/atomic_test.cpp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**核心概念**：`std::atomic<T>` 提供对类型 `T` 的原子读写操作，在多线程环境下消除数据竞争。\n",
    "\n",
    "**常见成员**：\n",
    "\n",
    "- `load()` / `store()`：原子读写。\n",
    "- `fetch_add()` / `fetch_sub()` / `fetch_or()` 等原子读-改-写操作。\n",
    "- `compare_exchange_strong()` / `compare_exchange_weak()`：比较交换（CAS）。\n",
    "\n",
    "**内存序（memory order）**：默认 `std::memory_order_seq_cst` 最安全；根据需求可选择 `relaxed`、`acquire/release` 等以获得更佳性能。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "业务场景示例\n",
    "\n",
    "- **高频计数器 / 指标采集**\n",
    "   在日志、监控或限流模块中，以 `std::atomic` 维护计数器（如请求数、错误数），避免互斥锁带来的阻塞开销。\n",
    "- **无锁队列 / 栈等数据结构**\n",
    "   基于原子操作（如 `compare_exchange_strong`）实现无锁数据结构，提高并发性能并减少线程上下文切换。\n",
    "- **引用计数与对象生命周期管理**\n",
    "   共享对象的引用计数可通过 `std::atomic<size_t>` 实现线程安全的加减操作，常见于智能指针或资源池。\n",
    "- **状态标志 / 开关量**\n",
    "   原子布尔或枚举用于表示组件状态（启动、停止、故障），各线程能无锁读取与更新。\n",
    "- **环形缓冲区或队列的生产者-消费者**\n",
    "   使用原子索引管理读写位置，配合内存序保证数据可见性，实现低延迟消息队列。\n",
    "- **自旋锁 / Ticket 锁的实现**\n",
    "   原子操作是自旋锁等轻量级同步原语的基础，用于在用户态实现忙等锁。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用注意事项\n",
    "\n",
    "- **选择合适的内存序（memory order）**：默认 `std::memory_order_seq_cst` 最安全但最保守；根据需求选用 `memory_order_relaxed`、`acquire/release` 等以获得最佳性能，同时确保语义正确。\n",
    "- **配对使用 acquire/release**：写入共享数据前先更新，读取时使用 `acquire`，写入时使用 `release`，确保可见性。\n",
    "- **避免 ABA 问题**：在无锁结构中使用指针 CAS 时需防止 ABA，可借助标记位、版本号或 `std::atomic<std::shared_ptr>`。\n",
    "- **类型选择**：`std::atomic` 仅支持 trivially copyable 类型；复杂类型需用 `std::atomic<std::shared_ptr<T>>` 或自定义机制。\n",
    "- **自旋等待策略**：自旋消耗 CPU，适合临界区极短的场景。必要时添加 `std::this_thread::yield()` 或指数退避减少抢占。\n",
    "- **对齐与 false sharing**：多个原子变量若共享同一缓存行，可能导致性能下降；可使用 `alignas` 或 padding 避免 False Sharing。\n",
    "- **调试与测试**：原子操作常伴随弱一致性，测试时需在不同平台和优化级别下验证正确性，尽量引入工具（TSan 等）检查。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " 潜在缺陷 / 局限\n",
    "\n",
    "- **实现与推理复杂**：正确选择内存序并推理可见性极具挑战，一旦错误往往难以复现和定位。\n",
    "- **仍可能导致忙等开销**：自旋或频繁 CAS 会耗费 CPU，尤其在高争用下对性能不利。\n",
    "- **功能受限**：原子类型无法直接替代复杂同步需求；在需要顺序保证或组合状态变更时仍需锁或更高级机制。\n",
    "- **不可移除逻辑错误**：原子仅保证原子性，不会自动防止逻辑层面的竞态（如读-改-写流程中的业务规则错误）。\n",
    "- **硬件差异**：不同架构对内存序的实现成本差异很大，错误的序选择可能在某些 CPU 上表现良好，在其它平台上失败。\n",
    "- **难以与条件变量等协同**：原子变量本身不提供阻塞等待机制，如需等待状态变化仍需合并其他同步原语。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 原子读写"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| 关键词                     | 含义                                           | 说明                                                      |\n",
    "| -------------------------- | ---------------------------------------------- | --------------------------------------------------------- |\n",
    "| **原子访问**               | Load（读）与 Store（写）在内存上的不可分割操作 | 保证在多线程下不会出现“半写入、半读取”的状态              |\n",
    "| **内存序（memory order）** | 控制编译器和 CPU 可以如何重排指令              | 决定原子操作在可见性和有序性方面的 guarantees             |\n",
    "| **数据竞争**               | 至少一个线程写入，且读写访问不是“同步的”       | 使用原子操作可以避免数据竞争                              |\n",
    "| **可见性与顺序性**         | 线程之间对数据的观察顺序                       | Acquire/Release/SeqCst 保证有序传播；Relaxed 只保证原子性 |\n",
    "| **读-改-写（RMW）**        | `fetch_add`, `compare_exchange` 等组合操作     | 既读取旧值又写入新值，同样                                |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "常见误区与注意事项\n",
    "\n",
    "1. **只使用 `std::atomic` 不意味着自动正确**：必须选对内存序、保证其他数据同步。\n",
    "2. **原子只保护单个对象**：多字段互相关联时，用互斥锁或结构体中的单一原子加载全部状态。\n",
    "3. **不要将原子对象与非原子对象混用**：例如同时读写普通指针与原子指针会引发数据竞争。\n",
    "4. **`compare_exchange` 的两个内存序参数**：成功时使用第一个，失败时使用第二个（通常是更弱的 `memory_order_relaxed`）。\n",
    "5. **`volatile` ≠ 原子操作**：`volatile` 只抑制编译器优化，与线程同步无关。\n",
    "6. **关注 ABA 问题**：CAS 操作在某些无锁结构中需要额外版本号或 `std::atomic<std::shared_ptr>` 等手段。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [08_once_flag](./threadcodes/08_once_flag/once_flag_test.cpp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`std::once_flag` 与 `std::call_once` 搭配使用，确保指定的初始化逻辑在多线程环境中**无论被调用多少次，都只执行一次**。调用成功后，内部会把 `once_flag` 标记为“已执行”，后续线程再调用 `std::call_once` 时会立即返回而不会重复运行初始化代码。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "std::once_flag flag;\n",
    "\n",
    "void init_routine();            // 需要只执行一次的初始化任务\n",
    "std::call_once(flag, init_routine);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "业务场景示例\n",
    "\n",
    "- **懒加载单例初始化**\n",
    "   使用 `std::call_once` 配合 `std::once_flag` 确保单例对象只被构造一次，并保证线程安全的首次初始化。\n",
    "- **昂贵资源的延迟创建**\n",
    "   如数据库连接池、配置文件解析或大型缓存，只有在首次访问时才创建，避免程序启动阶段的额外成本。\n",
    "- **模块级别初始化**\n",
    "   在库或动态模块中执行一次性初始化逻辑（注册插件、加载全局表），防止多线程重复初始化。\n",
    "- **一次性逻辑注入**\n",
    "   在事件系统或回调框架中，确保某些回调注册逻辑只执行一次，即使多个线程尝试同时注册同一回调。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用注意事项\n",
    "\n",
    "- **配合 `std::call_once` 使用**：`std::once_flag` 必须与 `std::call_once` 搭配，不能手动重置或复制 flag。\n",
    "- **确保初始化函数无异常或正确处理异常**：若初始化函数抛出异常，`std::call_once` 会重置状态，下次调用仍会尝试初始化；需保证异常安全或自行捕获处理。\n",
    "- **避免长时间阻塞**：初始化函数中若执行耗时操作，会阻塞所有等待 `call_once` 完成的线程，应尽量缩短临界区或使用异步初始化策略。\n",
    "- **不可复制/移动**：`std::once_flag` 不可拷贝或移动，通常应声明为静态或全局对象，以延长生命周期。\n",
    "- **线程安全依赖**：`call_once` 内部会在 flag 上使用同步原语，避免在初始化函数中尝试再次调用 `call_once` 同 flag 造成潜在死锁。\n",
    "- **与惰性加载配合**：如果惰性资源需要销毁或重置，`once_flag` 不支持“重启”机制，需在设计上规避或采用其他同步手段。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "潜在缺陷 / 局限\n",
    "\n",
    "- **无法重新初始化**：`once_flag` 完成后不能复用，无法在程序运行时撤销或重建，适合只需初始化一次的场景。\n",
    "- **调试复杂**：初始化逻辑只运行一次且可能跨线程触发，若出现问题不易重现，调试困难。\n",
    "- **缺少返回值同步**：`call_once` 不直接返回初始化结果，如果需获取初始化产物，需要额外的数据结构（如静态变量或 `std::optional`）管理。\n",
    "- **阻塞其他线程**：在初始化期间，其他线程需等待，若初始化耗时过长将影响并发性能。\n",
    "- **异常处理棘手**：重复失败的初始化可能导致多次调用失败且无简单机制停止尝试，需要在初始化函数内部决定撤退或降级策略。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [09_async](./threadcodes/09_async/atomic_test.cpp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`std::async` 负责启动一个异步任务，并返回一个 `std::future`（或 `std::shared_future`）对象，用于在稍后获取任务结果或异常。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "auto fut = std::async(std::launch::async, [] {\n",
    "    return long_computation();\n",
    "});\n",
    "\n",
    "// ... 主线程可继续做别的事 ...\n",
    "\n",
    "auto value = fut.get();   // 阻塞直到异步任务完成，获取返回值或重新抛出异常"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "业务场景示例\n",
    "\n",
    "- **并行执行 CPU 密集任务**\n",
    "   利用 `std::async` 将复杂计算（如图像处理、数值分析）拆分到多个异步任务，充分使用多核 CPU。\n",
    "- **后台执行 I/O 操作**\n",
    "   在需要同时处理多个磁盘或网络 I/O 时，通过异步启动任务避免主线程阻塞，提升响应速度。\n",
    "- **延迟执行与懒惰求值**\n",
    "   某些计算结果可能并不总被使用，利用 `std::launch::deferred` 延迟执行，在调用 `get()` 时才计算，节约资源。\n",
    "- **快速原型并发结构**\n",
    "   适合对多任务并发流程进行快速实验，无需手动管理线程创建、同步与回收。\n",
    "- **组合任务 / 任务树**\n",
    "   作为一次性任务树节点，与其他异步任务组合，实现 Map/Reduce 或分层调度。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用注意事项\n",
    "\n",
    "- **选择正确的启动策略**：\n",
    "  - 默认策略 `std::launch::async | std::launch::deferred` 由实现决定是否立即并发或延迟执行。\n",
    "  - 指定 `std::launch::async` 可确保创建新线程或线程池任务。\n",
    "  - 指定 `std::launch::deferred` 将在 `get()`/`wait()` 时同步执行。\n",
    "- **必须调用 `get()` 或 `wait()`**：未获取 future 结果会在析构时阻塞或导致异常抛出；必须显式处理任务结果和异常。\n",
    "- **异常传播**：异步任务中抛出的异常会在 `future::get()` 时重新抛出，调用方需做好异常处理。\n",
    "- **线程资源管理**：频繁使用 `std::launch::async` 可能创建大量线程，需关注平台线程数量限制，必要时自建线程池。\n",
    "- **避免复制 `future`**：`std::future` 不可复制，仅可移动；若需要多个消费者，考虑 `std::shared_future`。\n",
    "- **任务内共享数据同步**：异步任务依然需要正确处理共享状态，必要时使用锁或原子操作。\n",
    "- **生命周期管理**：确保在任务结束前所访问的资源仍然有效，避免悬空引用或指针。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "潜在缺陷 / 局限\n",
    "\n",
    "- **不可控的线程创建**：默认策略可能导致实现选择立即执行于调用线程或创建新线程，不同平台表现不一致。\n",
    "- **缺乏取消机制**：标准 `std::async`/`future` 不提供中途取消任务的能力，一旦启动需运行到结束。\n",
    "- **线程池不可保证**：标准未要求实现采用线程池，频繁调用可能导致大量线程上下文切换和资源消耗。\n",
    "- **调试与性能可见性低**：缺少直接的任务跟踪、优先级控制与性能监控能力，相较专业任务调度库较弱。\n",
    "- **与事件循环集成困难**：`std::future` 缺少回调或通知机制，难以与 GUI 事件循环或异步框架（如 `asio`）无缝结合。\n",
    "- **延迟策略陷阱**：使用默认策略可能在期望并发时却延迟执行，导致性能不达预期；反之亦然。\n",
    "- **异常泄漏风险**：若从不调用 `get()`，任务异常会在 future 析构时终止程序或调用 `std::terminate`，需严防遗漏。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [10_promise](./threadcodes/10_promise/promise_test.cpp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- https://en.cppreference.com/w/cpp/thread/future.html\n",
    "- https://en.cppreference.com/w/cpp/thread/promise.html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`std::promise<T>` 和 `std::future<T>` 是 C++11 提供的配套工具，用于**手动在线程之间传递一次性结果或异常**。\n",
    "\n",
    "1. 创建 `std::promise<T>` 对象，并通过 `get_future()` 生成与之绑定的 `std::future<T>`。\n",
    "2. 将 `future` 交给消费者线程，`promise` 留在生产者线程。\n",
    "3. 生产者调用 `promise.set_value(value)` 或 `promise.set_exception(exception_ptr)`。\n",
    "4. 消费者线程调用 `future.get()` 阻塞等待，获取结果或重新抛出异常。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "std::promise<int> promise;\n",
    "std::future<int> fut = promise.get_future();\n",
    "\n",
    "std::thread producer([&] {\n",
    "    promise.set_value(42);          // 发布结果\n",
    "});\n",
    "\n",
    "int value = fut.get();              // 阻塞等待，返回 42\n",
    "producer.join();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "业务场景示例\n",
    "\n",
    "- **线程间结果传递**\n",
    "   工作线程执行复杂任务后，通过 `std::promise` 向主线程传递结果，主线程通过关联的 `future` 获取。\n",
    "- **异步任务自定义启动**\n",
    "   配合手动创建的 `std::thread`，在线程体中设置 `promise` 值，可灵活控制任务生命周期，相比 `std::async` 更易定制。\n",
    "- **多阶段管道**\n",
    "   在流水线或分阶段任务中，前一阶段完成后设定 `promise`，下一阶段通过 `future` 等待输入，实现同步与结果传递。\n",
    "- **异常跨线程传播**\n",
    "   异步任务发生异常时调用 `promise.set_exception()`，等待方在 `future.get()` 时能获取并处理异常。\n",
    "- **与事件循环桥接**\n",
    "   当使用第三方库的异步回调（如网络 I/O）时，可在回调中满足 `promise`，调用方以 `future` 形式等待结果，桥接回调式与同步等待。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用注意事项\n",
    "\n",
    "- **一次性设定**：`promise` 只能设置一次（无论是值还是异常），重复调用 `set_value`/`set_exception` 会抛出异常。\n",
    "- **及时获取 `future`**：在设置值之前必须创建并传递 `future`（通过 `promise.get_future()`）；重复调用 `get_future()` 会抛出异常。\n",
    "- **异常安全**：如果在设置值前 `promise` 被销毁，关联 `future` 将在 `get()` 时抛出 `std::future_error`，需确保 `promise` 生命周期足够长。\n",
    "- **线程同步**：`promise` 本身不提供锁，若多个线程要访问同一个 `promise` 对象，需额外采取同步措施。\n",
    "- **使用移动语义**：`promise` 可以移动但不可复制，移动后原对象进入无效状态，注意所有权转移。\n",
    "- **避免未设置即结束**：若线程在未设置值的情况下异常退出，应捕获异常并调用 `set_exception`，避免等待方永远阻塞。\n",
    "- **配合 `shared_future`**：若多个消费者需要结果，可在获取 future 后转为 `std::shared_future`。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "潜在缺陷 / 局限\n",
    "\n",
    "- **一次性通道**：`promise` 对应的结果只能设置一次，无法用于多次消息传递，若需要持续通信应使用队列或通道。\n",
    "- **手动管理开销**：相比 `std::async` 自动处理线程和异常，`promise` 需要手动管理线程启动、异常捕获与生命周期，增加复杂度。\n",
    "- **易遗忘设置**：在复杂逻辑中可能遗忘调用 `set_value` 或 `set_exception`，导致 `future` 永久等待。\n",
    "- **不可取消**：标准 `promise`/`future` 不支持取消机制，即使任务已无意义亦必须运行或手动中断线程。\n",
    "- **调试难度**：`promise` 与 `future` 的强耦合使得数据流跨线程传播，若出现死锁或逻辑错误，调试调用链较为困难。\n",
    "- **性能开销**：涉及动态分配和同步原语，相比轻量级的原子或锁，在高频率短任务场景中可能成为瓶颈。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [11_packaged_task](./threadcodes/11_packaged_task/packaged_task_test.cpp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`std::packaged_task<R(Args...)>` 将任意可调用对象（函数、Lambda、函数对象）封装成一次性异步任务：\n",
    "\n",
    "1. **构建任务**：`std::packaged_task<int(int)> task(fn);`\n",
    "2. **绑定 future**：`auto fut = task.get_future();`\n",
    "3. **调度执行**：通过 `task(args...)` 或将任务移动到线程/线程池运行。\n",
    "4. **获取结果**：在消费者侧调用 `future.get()`，获得返回值或异常。\n",
    "\n",
    "`packaged_task` 可以看作手工组合 `std::promise` + `std::future` 的快捷形式，并附带可调用对象。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "业务场景示例\n",
    "\n",
    "- **任务与线程分离管理**\n",
    "   预先把可调用对象包装成 `std::packaged_task`，将其放入任务队列，线程池或工作线程从队列取出任务执行，实现灵活的任务调度。\n",
    "- **延迟绑定任务执行环境**\n",
    "   将函数及其参数打包后，可以在未来的任意线程执行，适合需要在不同执行上下文之间传递计算逻辑的场景。\n",
    "- **自定义线程池实现**\n",
    "   在构建自定义线程池时，可把任务封装为 `packaged_task`，这样可获得对应的 `future` 以追踪执行结果。\n",
    "- **桥接回调与同步等待**\n",
    "   结合事件循环或异步回调，先把回调逻辑包装成 `packaged_task`，当外部事件触发时执行任务，同时主线程通过 `future` 获取结果。\n",
    "- **任务重试或迁移**\n",
    "   若某任务执行失败或需要转移到其他线程，可在未调用 `operator()` 前移动 `packaged_task` 到新的执行环境，保证任务可重调度。\n",
    "- **批量任务提交**\n",
    "   在生产者/消费者模式中，生产者创建多个 `packaged_task` 放入队列，消费者线程执行并返回 `future` 结果，用于批处理计算。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用注意事项\n",
    "\n",
    "- **一次性执行**：`packaged_task` 的 `operator()` 只能调用一次；调用后任务进入无效状态，不可重复执行。\n",
    "- **获取 `future`**：在执行之前应调用 `get_future()` 获取结果对象；多次调用 `get_future()` 会抛出 `std::future_error`。\n",
    "- **异常处理**：被包装的函数若抛出异常，`future.get()` 会重新抛出，需要调用方做好异常捕获。\n",
    "- **移动语义**：`packaged_task` 支持移动但不支持复制；在放入容器或队列时，需要使用 `std::move`。\n",
    "- **生命周期管理**：任务执行前确保 `packaged_task` 未被销毁，否则关联的 `future` 会在 `get()` 时抛出异常。\n",
    "- **线程安全**：`packaged_task` 自身不是线程安全的；若多个线程操作同一个任务对象，需要外部同步。\n",
    "- **与线程池配合**：在自定义线程池中，执行线程必须调用 `task()`（或 `operator()`）来触发任务，否则 `future` 会永久阻塞。\n",
    "- **避免卡住队列**：若任务执行需要等待外部条件，应考虑超时或取消策略，避免阻塞消费线程。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "潜在缺陷 / 局限\n",
    "\n",
    "- **一次性资源**：任务只能执行一次，无法复用包装对象；若需重复执行同一函数，需要重新创建 `packaged_task`。\n",
    "- **管理复杂度**：相比 `std::async`，需要手动安排任务入队、线程调度与异常处理，增加实现复杂度。\n",
    "- **性能开销**：包装和同步引入额外开销，对于极简任务或高频场景可能不如轻量方案（如 function + promise）。\n",
    "- **缺少取消机制**：一旦任务被提交，标准库不提供取消或中断机制，只能通过任务内部自行检查。\n",
    "- **难以调试**：任务在不同线程中执行，调试调用栈和跟踪数据流需要额外的日志与诊断工具。\n",
    "- **依赖 `future` 获取结果**：如果忘记获取 `future` 或在任务执行后才尝试 `get_future()`，会导致 `std::future_error`，需小心处理调用顺序。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [12_condition_variable_any](./threadcodes/12_condition_variable_any/condition_variable_any_test.cpp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`std::condition_variable_any` 是比 `std::condition_variable` 更通用的条件变量实现。**它可以与任何满足 `BasicLockable` 概念的锁类型配合**（即必须实现 `lock()` / `unlock()`，最好还能提供 `try_lock()` / `try_lock_for()` 等扩展）。典型流程：\n",
    "\n",
    "1. 准备互斥量（可为 `std::shared_mutex`、`std::recursive_mutex`、自定义锁等）。\n",
    "2. 使用该锁构造 `std::unique_lock<LockType>` 并锁定。\n",
    "3. 调用 `cv.wait(lock, predicate)` 或 `cv.wait_for(...)` 等待条件成立；wait 内部在等待时会自动解锁，在被唤醒后重新上锁。\n",
    "4. 条件满足后继续执行；通知端调用 `cv.notify_one()` / `cv.notify_all()` 唤醒等待者。\n",
    "\n",
    "与 `std::condition_variable` 相比，它提供了更高的锁类型兼容性，代价是内部存在虚拟调度或类型擦除，性能略低。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "业务场景示例\n",
    "\n",
    "- **自定义锁类型协同**\n",
    "   当需要与非 `std::mutex` 类型的锁（如自旋锁、读写锁、可重入互斥量、Boost 锁等）配合使用时，`std::condition_variable_any` 支持任意满足 BasicLockable 概念的锁类型。\n",
    "- **跨平台同步封装**\n",
    "   在封装统一同步接口时，可允许调用方传入不同的锁实现，通过 `condition_variable_any` 满足等待/通知需求。\n",
    "- **粒度细的锁适配**\n",
    "   某些数据结构使用细粒度互斥（例如分段锁、升级锁），需要条件变量与对应锁协同；`condition_variable_any` 能适配这些复杂锁。\n",
    "- **调度器 / 任务队列**\n",
    "   自定义线程池或任务调度器里，若内部锁不是 `std::mutex`（例如采用支持忙等的自适应锁），就可以使用 `condition_variable_any` 实现等待与唤醒。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用注意事项\n",
    "\n",
    "- **锁要求**：使用的锁类型必须满足 `BasicLockable`（提供 `lock()` / `unlock()`）并能与条件变量正确配合；若支持 `try_lock` 可提升性能。\n",
    "- **性能考量**：`condition_variable_any` 通常比 `std::condition_variable` 慢，因为内部需要对任意锁进行类型擦除处理；若仅使用 `std::mutex`，优先选择 `std::condition_variable`。\n",
    "- **等待前持锁**：与普通条件变量一致，调用 `wait` 前必须持有锁；`wait` 会解锁并在唤醒后重新加锁。\n",
    "- **搭配 `wait_for` / `wait_until`**：支持超时等待，正确处理超时返回并重新检查条件。\n",
    "- **虚假唤醒**：同样会发生伪唤醒，等待线程应在循环中检查条件。\n",
    "- **异常安全**：`wait` 和 `notify` 不抛异常；但锁类型可能抛出，需确保锁的异常安全性。\n",
    "- **避免死锁**：通知线程在发出 `notify_one`/`notify_all` 时不需要持锁，但若持锁要注意避免导致等待线程唤醒后立即阻塞。\n",
    "- **锁对象生命周期**：等待期间锁必须保持有效，通常需要将锁放在比条件变量更长寿命的作用域里。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "潜在缺陷 / 局限\n",
    "\n",
    "- **性能损耗**：由于泛型支持，需要额外的类型擦除与虚拟调用开销；在高频等待/通知场景下不如 `std::condition_variable` 高效。\n",
    "- **实现差异**：不同标准库实现对任意锁的支持细节可能有差异（尤其在旧平台），导致性能或兼容性问题。\n",
    "- **调试复杂**：与自定义锁组合使用，使得调试等待/通知路径更复杂，错误时难以定位。\n",
    "- **易用性较差**：缺少典型示例和文档，团队成员可能更熟悉 `std::condition_variable`，需要额外培训和代码规范。\n",
    "- **潜在死锁风险增加**：使用非传统锁时，若锁的解锁/加锁策略有特殊行为，等待线程可能陷入死锁，需严格验证锁实现。\n",
    "- **无法避免逻辑竞态**：同其它同步原语一样，仅提供等待唤醒机制，业务层条件判断仍需正确设计检查条件与状态更新逻辑。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 为什么“大多数线程相关类型都能移动/引用却不能拷贝”？"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **禁止拷贝** 是为了确保资源独占、避免双重释放、保持 RAII 的确定性、减少竞态。\n",
    "- **允许移动** 是为了在安全的前提下转移所有权。\n",
    "- **通过引用共享** 则是显式地表示“我不拥有，只是访问”"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "C++ 标准线程库中的核心类型（如 `std::thread`, `std::mutex`, `std::unique_lock`, `std::future`, `std::promise`, `std::packaged_task` 等）几乎都是 **move-only**（可移动、不可复制）。\n",
    "\n",
    "这是一个刻意的设计决策，背后有以下关键理念："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. **独占资源所有权（Single Ownership）**\n",
    "\n",
    "这些对象往往代表着系统级资源或唯一的同步语义，例如：\n",
    "\n",
    "- `std::thread` 拥有一个正在运行的操作系统线程；\n",
    "- `std::mutex` 代表一个互斥锁；\n",
    "- `std::unique_lock` 持有锁的所有权；\n",
    "- `std::promise` 管理一次性的结果通道；\n",
    "- `std::packaged_task` 封装一次性的任务及其结果通道。\n",
    "\n",
    "这些资源必须**只有一个主人**。如果允许复制，就会出现两个 C++ 对象“声称”拥有同一资源：\n",
    "\n",
    "```cpp\n",
    "std::thread t1(do_work);\n",
    "std::thread t2 = t1;   // 如果允许复制，t1 与 t2 都认为自己拥有同一个线程\n",
    "```\n",
    "\n",
    "此时谁负责 `join`？谁负责异常处理？两个对象都在析构时 `join()` 会导致双重等待，`detach()` 会导致任务失控。为了彻底杜绝这样的语义歧义，标准直接禁止拷贝。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2. **RAII 与确定性释放**\n",
    "\n",
    "C++ 倡导 RAII（资源获取即初始化）：对象生命周期结束时自动释放资源。`std::thread` 在析构前必须 `join` 或 `detach`；`std::mutex`/`std::unique_lock` 在析构时自动解锁；`std::promise` 析构时若未置值就会向 `future` 报告 `broken_promise`。\n",
    "\n",
    "若允许拷贝，RAII 的行为会变得不确定——资源到底何时、由谁释放不清晰。这会破坏 C++ 一贯的 deterministic cleanup 设计。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "3. **避免共享状态下的竞态与异常安全问题**\n",
    "\n",
    "假设复制是允许的，两份对象很可能被不同线程同时操作，导致内部状态数据竞争或重复设置异常。用静态分析去证明“拷贝后不会被并发访问”几乎不可能；标准选择在类型层面禁止复制，让潜在的并发 bug 降到最小。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "4. **与底层操作系统语义保持一致**\n",
    "\n",
    "大多数操作系统线程、互斥、条件变量等句柄本身就不支持“复制”，只有转移（move/dup）或引用（指针/句柄）的概念。C++ 标准库通过 move-only 设计与底层保持一致，避免引入虚构的语义。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "5. **语义区分：独占 vs. 共享**\n",
    "\n",
    "- 对于必须独占的资源，类型是 move-only：`std::thread`, `std::unique_lock`, `std::packaged_task`, `std::promise`, `std::future`。\n",
    "- 如果业务确实需要共享结果，标准提供显式的共享类型：`std::shared_future`（可复制）、`std::shared_ptr`（引用计数）、`std::atomic`（显式共享）。通过类型区分，让设计者一眼看出对象语义。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "6. **Move Semantics：安全地“转让所有权”**\n",
    "\n",
    "允许移动是为了处理“资源所有权需要变化”的场景。例如：\n",
    "\n",
    "\n",
    "```cpp\n",
    "std::thread worker(do_work);\n",
    "\n",
    "// 转移给另一个管理者\n",
    "std::thread supervisor = std::move(worker);  // worker 变成空对象\n",
    "```\n",
    "\n",
    "移动语义确保源对象被置于“无资源”状态（如 `worker` 变成 not joinable），新的对象唯一地持有资源。这与 `std::unique_ptr` 同构。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "7. **引用或指针共享：显式表达共享意图**\n",
    "\n",
    "如果确实需要多个地方访问同一个线程对象或锁，可以使用引用或指针：\n",
    "\n",
    "```cpp\n",
    "void use_thread(std::thread& t);\n",
    "void use_mutex(std::mutex& m);\n",
    "```\n",
    "\n",
    "引用（或指针）清晰地表达“这里是共享访问，不拥有资源”；也避免了潜在的生命周期管理重复问题。标准库提供 `std::ref`/`std::cref`、`std::reference_wrapper`，方便在模板中传递引用。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "8. **历史脉络与设计哲学**\n",
    "\n",
    "于 C++11 并发库设计时（参阅 N2406、N2447 等提案），委员会明确强调：\n",
    "\n",
    "- 线程、锁等应当遵循资源句柄模式；\n",
    "- 复制语义会带来过高的实现复杂度与使用陷阱；\n",
    "- Move-only 类型在 C++11 中已成为资源管理的标准手段（`std::unique_ptr`）。\n",
    "\n",
    "这与 C++ 的整体设计哲学一致：**提供底层能力，避免隐藏成本或不明确语义**；通过静态类型体系阻止常见误用。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "codemirror_mode": "text/x-c++src",
   "file_extension": ".cpp",
   "mimetype": "text/x-c++src",
   "name": "C++17",
   "version": "17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
